package com.jintian.smart.kernel.flowable.component.action.task;

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.stream.Collectors;

import com.jintian.smart.kernel.core.flow.FlowAction;
import com.jintian.smart.kernel.core.flow.ProcessControl;
import com.jintian.smart.kernel.flowable.component.action.base.AbstractTaskAction;
import com.jintian.smart.kernel.flowable.context.DefaultProcessContext;
import com.jintian.smart.kernel.flowable.flowable.cmd.TransformTaskCmd;
import org.flowable.bpmn.model.FlowNode;
import org.flowable.bpmn.model.UserTask;
import org.flowable.common.engine.impl.identity.Authentication;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.DelegationState;
import org.flowable.task.api.Task;
import org.flowable.task.api.TaskInfo;
import org.flowable.task.service.impl.persistence.entity.TaskEntity;
import org.springframework.stereotype.Component;


/**
 * 委派、加签
 */
@Component
public class TransformTaskAction extends AbstractTaskAction {
    @Override
    public FlowAction getAction() {
        return FlowAction.transform;
    }

    @Override
    protected List<TaskInfo> innerExecute(TaskEntity task, ProcessControl processControl) throws Exception {
        if (DelegationState.PENDING.equals(task.getDelegationState())) {
            if (Authentication.getAuthenticatedUserId().equals(task.getAssignee())) {
                // 当前操作者是被委托人
                throw new IllegalAccessException("被委托人不允许将任务转发给他人");
            }
        }
        ProcessInstance pi = this.getProcessInstance(task.getProcessInstanceId());
        try (DefaultProcessContext context = (DefaultProcessContext) this.processContextProvider.createInstance(
                pi.getProcessDefinitionKey(), task.getTaskDefinitionKey(), this.getAction(),
                task.getProcessInstanceId(), task.getId(), pi.getBusinessKey(), processControl);) {
            this.beforeAction(task, context, this.getAction());
            List<TaskInfo> ret = this.invokeAction(context, new Callable<List<TaskInfo>>() {
                @Override
                public List<TaskInfo> call() throws Exception {
                    return transformTask(task, processControl);
                }
            });
            return ret;
        }
    }

    /**
     * 环节内任务转发执行执行者
     *
     * @param currentTask
     * @param processControl
     * @return
     */
    private List<TaskInfo> transformTask(TaskEntity currentTask, ProcessControl processControl) {
        return this.managementService().executeCommand(new TransformTaskCmd(currentTask.getId(), processControl))
                .stream().map(e -> (TaskInfo) e).collect(Collectors.toList());
    }

    @Override
    public List<FlowNode> queryTaskNextActivityNode(Task task) {
        return Arrays.asList((UserTask) this.getMainProcess(task.getProcessDefinitionId()).getFlowElement(task.getTaskDefinitionKey()));
    }
}
